﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Security.Cryptography;
using System.Text;
using System.Web.Mvc;
using AmazeUI.bll.Open.OpenModel;
using AmazeUI.bll.Open.Weixin;
using AmazeUI.Imodel.Res;
using Com;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WebCommon;

namespace AmazeUI.bll.Open.WeixinPay
{


    /// <summary>
    /// 回调处理基类
    /// 主要负责接收微信支付后台发送过来的数据，对数据进行签名验证
    /// 子类在此类基础上进行派生并重写自己的回调处理过程
    /// </summary>
    public class WxNotifyPayLogModel : INotifyPayLog
    {
        /// <summary>
        /// 返回ok
        /// </summary>
        public static string retok
        {
            get
            {
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
            }
        }
        /// <summary>
        /// 返回FAIL
        /// </summary>
        public static string retno
        {
            get
            {
                return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
            }
        }

        /// <summary>
        /// 接收从微信支付后台发送过来的数据并验证签名
        /// </summary>
        /// <returns>微信支付后台返回的数据</returns>
        public static WxNotifyPayLogModel GetNotifyModel(Stream stream)
        {

            //接收从微信后台POST过来的数据
            var str = WxCommon.GetInputStream(stream);
            var sd = WxCommon.FromXml(str);
            if (sd == null)
            {
                return null;
            }
            else
            {
               var b= CheckSign(sd);
                if (b)
                {
                    return JObject.FromObject(sd).ToObject<WxNotifyPayLogModel>();
                }
                else
                {
                    return null;
                }
              
            }

        }

        public static bool CheckSign(SortedDictionary<string, string> sd)
        {
            //如果没有设置签名，则跳过检测
            if (string.IsNullOrWhiteSpace(sd["sign"]))
            {
                return false;
            }

            //在本地计算新的签名
            string cal_sign = MakeSign(sd);

            if (cal_sign == sd["sign"])
            {
                return true;
            }

            return false;
        }
        /**
      * @生成签名，详见签名生成算法
      * @return 签名, sign字段不参加签名
      */
      static  string MakeSign(SortedDictionary<string, string> sd)
        {
            //转url格式
            string str = WxCommon.ToUrl(sd);
            //在string后加入API KEY
            str += "&key=" + WxPackage.Key;
            //MD5加密
            var md5 = MD5.Create();
            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            var sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字符转为大写
            return sb.ToString().ToUpper();
        }

        public string appid { get; set; }
        public string mch_id { get; set; }
        public string device_info { get; set; }
        public string nonce_str { get; set; }
        public string sign { get; set; }
        public string result_code { get; set; }
        public string err_code { get; set; }
        public string err_code_des { get; set; }
        public string openid { get; set; }
        public string is_subscribe { get; set; }
        public string trade_type { get; set; }
        public string bank_type { get; set; }
        public string total_fee { get; set; }
        public string fee_type { get; set; }
        public string cash_fee { get; set; }
        public string cash_fee_type { get; set; }
        public string coupon_fee { get; set; }
        public string coupon_count { get; set; }
        public string transaction_id { get; set; }
        public string out_trade_no { get; set; }
        public string attach { get; set; }
        public string time_end { get; set; }
        public string S { get; set; }

        /// <summary>
        /// 获取原始字符串
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string GetNotify(Stream stream)
        {
            return WxCommon.GetInputStream(stream);
        }

        public string Errcode { get { return string.IsNullOrWhiteSpace(this.err_code) ? null : this.err_code + " " + this.err_code_des; } set { } }
        public string PayTime { get { return this.time_end; } set { } }

        public string PayBank { get { return this.bank_type; } set { } }
        public string PayTypeName { get { return this.trade_type; } set { } }


        public int PayTypeId { get { return 0; } set { } }
        public string Remarks
        {
            get { return this.attach; }
            set { }
        }

        public string PartyOrderNo
        {
            get { return this.transaction_id; }
            set { }
        }

        public string PayTyp { get { return "Wx"; } set { } }
        public string OrderNo { get { return this.out_trade_no; } set { } }
    }
}